package cn.sh.library.mgts.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
import org.elasticsearch.action.bulk.BackoffPolicy;
import org.elasticsearch.action.bulk.BulkProcessor;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestClientBuilder;
import org.elasticsearch.client.RestClientBuilder.HttpClientConfigCallback;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.lucene.search.function.CombineFunction;
import org.elasticsearch.common.lucene.search.function.FunctionScoreQuery.ScoreMode;
import org.elasticsearch.common.unit.ByteSizeUnit;
import org.elasticsearch.common.unit.ByteSizeValue;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder;
import org.elasticsearch.index.query.functionscore.FunctionScoreQueryBuilder.FilterFunctionBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.index.query.functionscore.WeightBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.sh.library.mgts.common.Constant;
import cn.sh.library.mgts.framework.factory.ESClientSpringFactory;

public class RestHighLevelClientTest {

	private static Logger logger = LoggerFactory.getLogger(RestHighLevelClientTest.class);
	public static void main(String[] args) throws IOException {
		final CredentialsProvider credentialsProvider =
			    new BasicCredentialsProvider();
			credentialsProvider.setCredentials(AuthScope.ANY,
			    new UsernamePasswordCredentials("elastic", "horizon-es-123"));

			RestClientBuilder builder = RestClient.builder(
			    new HttpHost("10.1.30.127", 9200, "http"), new HttpHost("10.1.30.128", 9200, "http"))
			    .setHttpClientConfigCallback(new HttpClientConfigCallback() {
			        @Override
			        public HttpAsyncClientBuilder customizeHttpClient(
			                HttpAsyncClientBuilder httpClientBuilder) {
			            return httpClientBuilder
			                .setDefaultCredentialsProvider(credentialsProvider);
			        }
			    });
		
		RestHighLevelClient restHighLevelClient = new RestHighLevelClient(builder);

		List<Map<String, String>> res = new ArrayList<>();

		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
		searchSourceBuilder.size(10);
		
		FilterFunctionBuilder[] list = new FilterFunctionBuilder[2]; 
		ScoreFunctionBuilder<WeightBuilder> titleScore = new WeightBuilder();
		titleScore.setWeight(50);
		QueryBuilder titleQueryBuilder = QueryBuilders.matchPhraseQuery("search.title_keyword", "马克思");
		FilterFunctionBuilder titleFuncBuilder = new FilterFunctionBuilder(titleQueryBuilder, titleScore);
		list[0] = titleFuncBuilder;
		
		ScoreFunctionBuilder<WeightBuilder> creatorScore = new WeightBuilder();
		creatorScore.setWeight(40);
		QueryBuilder creatorQueryBuilder = QueryBuilders.matchPhraseQuery("search.author_keyword", "马克思");
		FilterFunctionBuilder creatorFuncBuilder = new FilterFunctionBuilder(creatorQueryBuilder, creatorScore);
		list[1] = creatorFuncBuilder;

//		list.toArray(a)
		BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
		boolQueryBuilder.should(titleQueryBuilder).should(creatorQueryBuilder);
		
		FunctionScoreQueryBuilder functionScoreQueryBuilder = QueryBuilders.functionScoreQuery(boolQueryBuilder, list).scoreMode(ScoreMode.SUM).boostMode(CombineFunction.MAX);
		searchSourceBuilder.query(functionScoreQueryBuilder);
		searchSourceBuilder.sort("_score").sort("sort.date", SortOrder.DESC);	
		
		
		//分面-loc
		TermsAggregationBuilder locAggregation = AggregationBuilders.terms("agg_loc")
				.field("location.keyword").size(999);

		//分面-col
		TermsAggregationBuilder colAggregation = AggregationBuilders.terms("agg_col")
				.field("collection.keyword").size(999);
		
		//分面-publis_date
		TermsAggregationBuilder pubDateAggregation = AggregationBuilders.terms("agg_pub_date")
				.field("view.publish_date.keyword").size(20);
		
		searchSourceBuilder.aggregation(colAggregation).aggregation(locAggregation).aggregation(pubDateAggregation);
		
		SearchRequest searchRequest = new SearchRequest(Constant.BIB_INDEX_NAME);
		searchRequest.source(searchSourceBuilder);
		try {
			SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
//			searchResponse.getHits().forEach(action -> {
//				res.add((Map<String, String>) action.getSourceAsMap().get("location"));
//			});
			Terms locAgg = searchResponse.getAggregations().get("agg_loc");
		} catch (IOException e) {
			e.printStackTrace();
		}
		
//		IndexRequest addIndex = new IndexRequest().index("posts").id("10000").source(Constant.JOIN_RELATION_PARENT_JSON.toString(), XContentType.JSON);
//		IndexRequest one = new IndexRequest("posts").id("1")
//		        .source(XContentType.JSON, "title",
//		                "In which order are my Elasticsearch queries executed?");
//		IndexResponse indexResponse = restHighLevelClient.index(addIndex, RequestOptions.DEFAULT);
//		BulkProcessor.Listener listener = new BulkProcessor.Listener() { 
//		    @Override
//		    public void beforeBulk(long executionId, BulkRequest request) {
//		        
//		    }
//
//		    @Override
//		    public void afterBulk(long executionId, BulkRequest request,
//		            BulkResponse response) {
//		        
//		    }
//
//		    @Override
//		    public void afterBulk(long executionId, BulkRequest request,
//		            Throwable failure) {
//		        
//		    }
//		};
//
//		BulkProcessor bulkProcessor = BulkProcessor.builder(
//		        (request, bulkListener) ->
//		        restHighLevelClient.bulkAsync(request, RequestOptions.DEFAULT, bulkListener),
//		        listener).build();
//		
//		IndexRequest addIndex = new IndexRequest().index(Constant.BIB_INDEX_NAME).id("10000").source(Constant.JOIN_RELATION_PARENT_JSON.toString(), XContentType.JSON);
//		IndexRequest one = new IndexRequest("posts").id("1")
//		        .source(XContentType.JSON, "title",
//		                "In which order are my Elasticsearch queries executed?");
//		IndexRequest two = new IndexRequest("posts").id("2")
//		        .source(XContentType.JSON, "title",
//		                "Current status and upcoming changes in Elasticsearch");
//		IndexRequest three = new IndexRequest("posts").id("3")
//		        .source(XContentType.JSON, "title",
//		                "The Future of Federated Search in Elasticsearch");
//
//		bulkProcessor.add(one);
//		bulkProcessor.add(two);
//		bulkProcessor.add(three);
//		bulkProcessor.flush();
//		bulkProcessor.close();
		try {
			restHighLevelClient.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
